package proto

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
)

type Message struct {
	Code int32
	Msg  string
	Data interface{}
}

// Encode 将消息编码
func Encode(message Message, cmd, scmd int32) ([]byte, error) {
	// 读取消息的长度，转换成int32类型（占4个字节）
	messageJson, _ := json.Marshal(message)
	var length = int32(len(messageJson))
	var pkg = new(bytes.Buffer)
	// 写入消息头
	err := binary.Write(pkg, binary.LittleEndian, length+8)
	if err != nil {
		return nil, err
	}
	// 写入cmd
	err = binary.Write(pkg, binary.LittleEndian, cmd)
	if err != nil {
		return nil, err
	}
	// 写入scmd
	err = binary.Write(pkg, binary.LittleEndian, scmd)
	if err != nil {
		return nil, err
	}
	// 写入消息实体
	err = binary.Write(pkg, binary.LittleEndian, messageJson)
	if err != nil {
		return nil, err
	}
	return pkg.Bytes(), nil
}

// Decode 解码消息
func Decode(reader *bufio.Reader) (cmd, scmd int32, message string, err error) {
	// 读取消息的长度
	lengthByte, _ := reader.Peek(4) // 读取前4个字节的数据
	lengthBuff := bytes.NewBuffer(lengthByte)
	var length int32
	err = binary.Read(lengthBuff, binary.LittleEndian, &length)
	if err != nil {
		return 0, 0, "", err
	}
	// Buffered返回缓冲中现有的可读取的字节数。
	if int32(reader.Buffered()) < length+4 {
		return 0, 0, "", err
	}

	// 读取真正的消息数据
	pack := make([]byte, int(4+length))
	_, err = reader.Read(pack)
	if err != nil {
		return 0, 0, "", err
	}
	message = string(pack[12:])
	fmt.Printf("hlen: %v  rlen: %v \n", length, len(message)+8)
	if int(length) != len(message)+8 {
		//结果长度不对
		return 0, 0, "", errors.New("packet length invalid")
	}
	_ = binary.Read(bytes.NewBuffer(pack[4:8]), binary.LittleEndian, &cmd)
	_ = binary.Read(bytes.NewBuffer(pack[8:12]), binary.LittleEndian, &scmd)
	return cmd, scmd, message, nil
}
